package gacha

import (
	"net/url"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

type GaCha struct {
	Uid       string `json:"uid"`
	GachaType string `json:"gacha_type"`
	ItemId    string `json:"item_id"`
	Count     string `json:"count"`
	Time      string `json:"time"`
	Name      string `json:"name"`
	Lang      string `json:"lang"`
	ItemType  string `json:"item_type"`
	RankType  string `json:"rank_type"`
	Id        string `json:"id"`
}

type JsonData struct {
	RetCode int    `json:"retcode"`
	Message string `json:"message"`
	Data    struct {
		Page   string  `json:"page"`
		Size   string  `json:"size"`
		Total  string  `json:"total"`
		Region string  `json:"region"`
		List   []GaCha `json:"list"`
	} `json:"data"`
}

type Config struct {
	RetCode int    `json:"retcode"`
	Message string `json:"message"`
	Data    struct {
		Region        string `json:"region"`
		GachaTypeList []struct {
			Id   string `json:"id"`
			Key  string `json:"key"`
			Name string `json:"name"`
		} `json:"gacha_type_list"`
	} `json:"data"`
}

var (
	CnPathName    = `原神`
	OtherPathName = `Genshin Impact`
)

func LocalLoad(name string, ch *Ch) {
	defer ch.close()

	ch.sendMessage(`开始尝试获取祈愿数据...`)
	home, err := os.UserHomeDir()
	if err != nil {
		ch.sendError(err.Error())
		return
	}
	ch.sendMessage(`已获取用户目录`)
	f := filepath.Join(home, `AppData`, `LocalLow`, `miHoYo`, name, `output_log.txt`)
	b, err := os.ReadFile(f)
	if err != nil {
		ch.sendError(err.Error())
		return
	}
	ch.sendMessage(`已读取游戏日志`)
	reg, err := regexp.Compile(`OnGetWebViewPageFinish:(http.*)`)
	//reg, err := regexp.Compile(`Diagnostics(.*)`)
	if err != nil {
		ch.sendError(err.Error())
		return
	}
	match := reg.FindAllStringSubmatch(string(b), -1)
	if match == nil || len(match) == 0 {
		ch.sendError(`请先在游戏中打开祈愿界面的详情或者历史记录后再试！`)
		return
	}
	ch.sendMessage(`已读取到访问的祈愿历史记录网址，正在分析...`)
	param := Param{}
	for i := len(match) - 1; i >= 0; i-- {
		if len(match[i]) >= 2 {
			s := match[i][1]
			t, err := url.Parse(s)
			if err != nil {
				continue
			}
			q := t.Query()
			if q.Get(`authkey_ver`) != `` && q.Get(`lang`) != `` && q.Get(`authkey`) != `` {
				if strings.Contains(t.Hostname(), `webstatic-sea`) || strings.Contains(t.Hostname(), `hk4e-api-os`) {
					param.Url = `https://hk4e-api-os.mihoyo.com`
				} else {
					param.Url = `https://hk4e-api.mihoyo.com`
				}
				param.AuthKeyVer = q.Get(`authkey_ver`)
				param.AuthKey = q.Get(`authkey`)
				param.Lang = q.Get(`lang`)
				break
			}
		}
	}

	if param.Url == `` || param.AuthKey == `` {
		ch.sendError(`分析祈愿历史记录网址失败，请重新在游戏中打开祈愿界面的详情或者历史记录后再试！`)
		return
	}
	ch.sendMessage(`祈愿历史记录网址分析成功，开始获取祈愿数据...`)
	loadWithParam(param, true, ch)
}

func AuthLoad(param Param, save bool, ch *Ch) {
	defer ch.close()

	loadWithParam(param, save, ch)
}

func loadWithParam(param Param, save bool, ch *Ch) {
	query := url.Values{}
	query.Set(`authkey_ver`, param.AuthKeyVer)
	query.Set(`lang`, param.Lang)
	query.Set(`authkey`, param.AuthKey)

	data, uid, err := load(param.Url, query, ch)
	if err != nil {
		ch.sendError(err.Error())
		return
	}
	if uid == `` {
		ch.sendError(`获取UID失败`)
		return
	}
	data = merge(uid, save, data, ch)
	//还需要和本地数据进行对比、合并
	ch.sendData(data)
}

func merge(uid string, save bool, data map[string][]GaCha, ch *Ch) map[string][]GaCha {
	if save {
		ch.sendMessage(`祈愿数据获取完毕，数据所属UID为：` + uid + `，正在尝试对历史数据（如有）进行合并、存储...`)
	} else {
		ch.sendMessage(`祈愿数据获取完毕，数据所属UID为：` + uid + `，正在尝试对历史数据（如有）进行合并...`)
	}
	//要对历史数据和新数据进行合并
	//1.先读取历史数据，如没有，直接存储新数据
	//2.如果有，就先将历史数据循环一遍，将id存储起来，然后将新数据遍历，也将id存储起来，同时判断有没有新数据是历史数据中没有的
	//3.如果有，就再遍历一次历史数据，将不在新数据中的数据追加到新数据中，将历史数据备份，存储新数据，返回新数据
	old := loadJson(uid)
	if old == nil {
		if save {
			ch.sendMessage(`未检测到历史数据，正在存储数据，并直接返回最新数据...`)
			saveJson(uid, data, ch)
		} else {
			ch.sendMessage(`未检测到历史数据，直接返回最新数据...`)
		}
		return data
	}
	oldIds := map[string]map[string]bool{}
	newIds := map[string]map[string]bool{}
	hasNew := false
	for n, d := range old {
		oldIds[n] = map[string]bool{}
		for _, g := range d {
			oldIds[n][g.Id] = true
		}
	}
	for n, d := range data {
		newIds[n] = map[string]bool{}
		oi, ok := oldIds[n]
		if !ok {
			hasNew = true
		}
		for _, g := range d {
			newIds[n][g.Id] = true
			if !hasNew && ok {
				if _, ok1 := oi[g.Id]; !ok1 {
					hasNew = true
				}
			}
		}
	}
	if !hasNew {
		if save {
			ch.sendMessage(`本次获取的数据和上次获取的数据无变更，跳过存储数据，并直接返回最新数据`)
		} else {
			ch.sendMessage(`本次获取的数据和上次获取的数据无变更，直接返回最新数据`)
		}
		return data
	}

	for n, d := range old {
		ni, ok := newIds[n]
		if !ok {
			ni = map[string]bool{}
		}
		for _, g := range d {
			if _, ok1 := ni[g.Id]; !ok1 {
				data[n] = append(data[n], g)
			}
		}
	}
	if save {
		ch.sendMessage(`检测到本次获取到了新的祈愿数据，正在将历史数据备份并存储合并后的数据...`)
		saveJson(uid, data, ch)
	}
	return data
}
